use axum::{routing::post, Router};
use axum_demo::handler;

use axum_demo::middlewares::server_time::ServerTimeLayer;
use nacos_sdk::api::constants;
use nacos_sdk::api::naming::{NamingService, NamingServiceBuilder, ServiceInstance,
};
use nacos_sdk::api::props::ClientProps;
use tower::ServiceBuilder;
use tower_http::compression::CompressionLayer;
use tower_http::trace::{DefaultMakeSpan, DefaultOnRequest, DefaultOnResponse, TraceLayer};
use tower_http::LatencyUnit;
use tracing::Level;


#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    dotenv::dotenv().ok();

    let app = Router::new()
    .nest(
        "/user",
        Router::new()
            .route("/register", post(handler::user::register))
            .route("/login", post(handler::user::login)),
    )
    .nest(
        "/book",
        Router::new()
            .route("/create", post(handler::book::create_book))
            .route("/search", post(handler::book::search_book))
            .route("/update", post(handler::book::update_book))
            .route("/delete", post(handler::book::delete_book)),
    );

    let client_props = ClientProps::new()
    .server_addr(constants::DEFAULT_SERVER_ADDR)
    .namespace("")
    .app_name("rust-nacos-sdk-demo");
let naming_service = NamingServiceBuilder::new(client_props)
        .enable_auth_plugin_http() // TODO You can choose not to enable auth
        .build()?;
    let service_instance1 = ServiceInstance {
        ip: "127.0.0.1".to_string(),
        port: 3000,
        ..Default::default()
    };

    let _register_instance_ret = naming_service
    .batch_register_instance(
        "rust-axum-test".to_string(),
        Some(constants::DEFAULT_GROUP.to_string()),
        vec![service_instance1],
    )
    .await;
tokio::time::sleep(tokio::time::Duration::from_millis(666)).await;

// let instances_ret = naming_service
//     .get_all_instances(
//         "axum-rust-service".to_string(),
//         Some(constants::DEFAULT_GROUP.to_string()),
//         Vec::default(),
//         false,
//     )
//     .await;
// match instances_ret {
//     Ok(instances) => tracing::info!("get_all_instances {:?}", instances),
//     Err(err) => tracing::error!("naming get_all_instances error {:?}", err),
// }

let app1 = app.layer(
    ServiceBuilder::new()
        .layer(
            TraceLayer::new_for_http()
                .make_span_with(DefaultMakeSpan::new().include_headers(true))
                .on_request(DefaultOnRequest::new().level(Level::INFO))
                .on_response(
                    DefaultOnResponse::new()
                        .level(Level::INFO)
                        .latency_unit(LatencyUnit::Micros),
                ),
        )
        .layer(CompressionLayer::new().gzip(true).br(true).deflate(true))
        .layer(ServerTimeLayer),
);

    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
    axum::serve(listener, app1.into_make_service()).await.unwrap();

    Ok(())
}

